package org.vaadin.nf4v.core.config.builder;

import org.vaadin.nf4v.core.NavigableWindow;
import org.vaadin.nf4v.core.config.ContextConfig;
import org.vaadin.nf4v.core.config.ContextConfigurationException;
import org.vaadin.nf4v.core.config.NavigationConfig;
import org.vaadin.nf4v.core.config.process.NavigationConfigProcessor;
import org.vaadin.nf4v.core.handler.Handler;

/**
 * Context configuration builder (DSL).
 */
public class ContextConfigBuilder {
    private ContextConfig contextConfig;
    private NavigationConfigProcessor navigationConfig;

    ContextConfigBuilder(ContextConfig contextConfig, NavigationConfigProcessor navigationConfig) {
        this.contextConfig = contextConfig;
        this.navigationConfig = navigationConfig;
    }

    /**
     * Sets window class for context.
     * Window should extend NavigableWindow.
     *
     * @param clazz context window class
     * @return context builder instance
     */
    public ContextConfigBuilder window(Class<? extends NavigableWindow> clazz) {
        if (clazz == null) {
            throw new ContextConfigurationException("Window name can't be null");
        }
        if (contextConfig.getWindowClass() != null) {
            throw new ContextConfigurationException("Window class for context '" + contextConfig.getName() +
                    "' already set to: " + contextConfig.getWindowClass().getName());
        }

        contextConfig.setWindowClass(clazz);
        return this;
    }

    /**
     * Marks current context window as main window.
     * This window will be instantiated first and set with Application#setMainWindow().
     * If no window is marked as main, first registered context window will be set as main window.
     *
     * @return context builder instance
     */
    public ContextConfigBuilder asMainWindow() {
        for (ContextConfig config : navigationConfig.getNavigationConfig().getContextConfigs()) {
            if (config.getName().equals(contextConfig.getName())) continue;
            if (config.isMainWindow()) {
                throw new ContextConfigurationException("Main context is already set to '" + config.getName() + "'");
            }
        }
        contextConfig.setMainWindow(true);
        return this;
    }

    /**
     * ALlows to register context configuration parameter.
     *
     * @param name  parameter name
     * @param value parameter value
     * @return context builder instance
     */
    public ContextConfigBuilder param(String name, String value) {
        contextConfig.setParam(name, value);
        return this;
    }

    /**
     * Allows to set theme for context.
     * This theme will be applied to window which represents this context.
     *
     * @param name theme name
     * @return context builder instance
     */
    public ContextConfigBuilder theme(String name) {
        contextConfig.setTheme(name);
        return this;
    }

    /**
     * Shortcut method to register default handler.
     *
     * @param handler handler instance
     * @return context builder instance
     */
//    public <T extends Handler> ContextConfigBuilder handler(T handler) {
//        navigationConfig.registerHandler(contextConfig, handler);
//        return this;
//    }
    //todo pending handlers dsl until proper handler instance registration
}
